Capcom "6C80" Sound Engine/Music Format Documentation ===================================================== version 0.4 (22nd April 2013) by Matrixz (best viewed with monospaced font) Changes ------- Removed Duck Tales 2 and Chip 'n Dale 2 from games list. Their engines are totally different (But they are similar to each other.) More accurate info on Instruments. More accurate info for "Command $04 and Break Command Flags" Updated info on Sound Effects. More info on version differences. Basic info on the SNES SPC700 version. General polishing. Games that use this sound engine -------------------------------- Darkwing Duck (Uses no bankswitching) Destiny Of An Emperor 2 Gargoyle's Quest 2 MegaMan 3 MegaMan 4 MegaMan 5 MegaMan 6 Mighty Final Fight TaleSpin The Little Mermaid (Uses no bankswitching) Wily and Light's Rockboard (Doesn't use bankswitching, but has MMC3 bankswitch code.) Games that use this sound engine, but an earlier/alternate version. (See further down). --------------------------------------------------------------------------------------- Adventures in the Magic Kingdom Chip 'n Dale: Rescue Rangers Little Nemo: The Dream Master Street Fighter 2010 6C80?? ------ Had to give the thing a name, so i did after what's usually byte 2 and 3 in the sound engine. Acknowledgements ---------------- Credits to Sephiroth3 for insight on music data. Thanks to MartsINY for further testing the Command 04 flags, plus other stuff. Thanks to Infidelity for MM1/2 command conversion list. This is a old document which have been updated because of personal use, plus it seems that its helped hackers. Earlier/Alternate Version differences ------------------------------------- Some NES games (list at top) use a version of this engine with some different locations for code and data. The first three bytes of the engine is 4C 3A 80 rather than 4C 6C 80. The Address Table is at memory location $8A00 instead of $8A40. (The first BGM or SFX pointer is at $8A03, or $A03 relative to the Sound Engine bank's address.) The engine's code size is smaller because it's less complex than the other variant. Instead of calling a subroutine that reads data (and does bankswitching if needed), it uses direct reading of sound data. ( LDA [$C1],y for BGM, and LDA [$D0],y for Sound effects. ) So this version doesn't support data at addresses higher than $BFFF. The common routine for reading BGM data is at $8556, and the one for sound effect data is at $8340. (Memory addresses.) Super NES SPC700 port --------------------- Capcom updated this engine to a SPC700 (the SNES sound chip) version used in some of their SNES releases. List of SNES games that uses it: (there may be more.) Final Fight / Final Fight Guy Final Fight 2 (.SPC offset $E20) Mega Man 7 Mega Man X1 - 3 Rockman & Forte Saturday Night Slammasters (.SPC offset $EA4) Super Ghouls 'N Ghosts The BGM data is very similar to the NES format. The main differences is that there are eight channel pointers instead of four. The pointers for channels, loops and jumps are still 16-bit Big-Endian, but they are SPC700 memory addresses. There is no single $00 byte at the start of BGM data. (normally) The address in SPC memory where a BGM is loaded seems to commonly be at or around $0DC0. In the Mega Man X SPC file set, the loaded BGM's data can be found at offset $EB0 in each SPC file. Most of the commands work a bit differently, for example command 07 (volume) still sets the channel volume but has a higher max value. Command 08 decides what sample is used (can vary depending on what sample data is loaded), and multiple instruments can use the same sample address, but different envelopes and effects. There are also additional command Id's, between $19-$1F, which were unused values on the NES. Final Fight and Super Ghouls 'N Ghosts are different from the others in that all BGM and Sound Effect data is loaded into SPC memory at all times. For those, at $F04 in a SPC file dump is the pointer table for BGM as well as Sound Effect Id's. The BGM's actually have a 00 as the first byte, like with BGM's in the NES variant. Game-specific notes ------------------- Darkwing Duck / Little Mermaid: Darkwing Duck uses MMC1 mapper board, and Little Mermaid uses UxROM (Mapper #2). The sound engine in both games has bankswitching code which is designed for MMC3. However, the bankswitching code is never executed in either game because both games only have one sound bank. (a MMC1 or UxROM ROM bank on $4000 bytes) Song Banks ====================================== Note: Much technical stuff ahead, for plain music hacking, skip to the next section. The games uses two * 8 KiloByte rom banks for the sound driver, music and sound effects wich is loaded to $8000 and $A000 in the memory map. For the games that do not use the MMC3 mapper, a plain 16kb bank is loaded into $8000. Some of the games uses an extra 3rd bank on 8kb for music and/or sound effects. This is read from when the address for sound data is $C000-$DFFF. Typically, a BGM starts at the end of the 2nd bank, and continues into the 3rd bank, so while it is playing, the engine may shift between reading from the 2nd and 3rd bank. When the engine reads a new byte from datas in the extra bank, this bank is temporarily swapped into $A000-$BFFF with the MMC3 mapper. It temporarily subtracts $2000 from the address to read from. To find the start of the sound engine bank, open the rom in a hex editor and try searching for $4C,$6C,$80. (If that doesn't work, try $4C,$3A,$80). Here is a little list of bank adresses in some games: ...........Sound Engine/.....................Additional ...............BGM/SFX.........BGM/SFX 2.......BGM/SFX ...........Bank - Adress - Bank - Adress - Bank - Adress MMC3 games: MegaMan 3: $16 - $2C010 $17 - $2E010 $18 - $30010 MegaMan 4: $1E - $3C010 $1F - $3E010 $1D - $3A010 MegaMan 5: $18 - $30010 $19 - $32010 $1A - $34010 MegaMan 6: $34 - $68010 $35 - $6A010 $36 - $6C010 MMC1 games (All data is in a 16k bank ($4000 bytes)): Darkwing: $03 - $C010 Notes for Mega Man 4, first song in each bank: $1E - Bright Man $1F - Skull Man $1D - Credit Song (19 in NSF file) Moving on, I will use Megaman 3 as an example for rom offsets. Song/Sound Effect Adress Table ============================== This adress table is in the 1st bank (Sound Engine Bank). The address table is usually at the offset of the Sound Engine Bank + $A43. (A few games has it at + $A03 instead.) In Megaman 3 this is at $2CA53. From there is a 2-byte pointer for every song and sound effect, in Big-Endian order (High byte then Low byte). These are NES Memory pointers, so you'll have to convert them to ROM pointers to find them in the rom. How-to: Subtract $8000 and add the offset of the Sound Engine Bank. This approach should always work, except if the bank layout is not straight-forward, as is the case with Mega Man 4. Example: Song pointer: $81A5 Sound Engine Bank adress: $30010 This means, the rom offset of the song is $301B5 For Megaman 4, $A000 converts to $3E010 (start of 2nd bank), while $C000 converts to $3A010 (start of 3rd bank). Megaman 3 / Shadow Man Tutorial ------------------------------- In MM3, the first two bytes of the Song/SFX Address Table is: 8C 9D $8C9D is the Memory pointer to the title scren theme. Needleman's music is the 2nd track of the game. The pointer for that is two bytes ahead, at $2CA55. The value found there is 90DF. Now for fnding the ROM offset of Shadowman's music. Note: The Id/index of a BGM can *usually* be found out going by the Track index of a NSF (NES Sound File). But in some cases, the NSF ripper has changed or optimized the song order so songs are not in the same order as in the pointer table. With a 6502 debugger like FCEUX, an approach to finding the Id of music is to set a execution breakpoint for $8003 when playing the game, then it should break right before music is initialized. Then you check what the A register contains, which is the sound Id. ($8003 is the address of the Sound initialization routine.) In the Mega Man 3 sound data, Shadowman is the 9th track. One method to find the pointer to the song is by this calculation: ([song index-counting from 0] * 2) + $2CA53. Song index - counting from 0: Meaning the song or sound effect index, where the 1st song is 0. Shadowman's music, counting from 0, is song #8. (8 * 2) + $2CA53 = $2CA63. Now, lets look at $2CA63: AA C2. AAC2 is the Memory pointer to Shadowman's music. Now here's how to turn that into a ROM pointer: Subtract $8000 then add $2C010. AAC2 - 8000 = 2AC2 2AC2 + 2C010 = 2EAD2. <- ROM location. Now, if you go to 2EAD2, there should be a 00, followed by AA CB AC 02 AD 1C AD A6. Those values are the pointers to each channel. Some very simple changes: Tune the pitch of the song 1 note down: Go to 2EADC, change the value from 03 to 02. Swap around Triangle (Bass) and Square 2 channels. Go to 2EAD5, place AD 1C, then place AC 02. Make it play fast: Go to 2EAE4, place 03. Check the "Song Format" section for detailed info on how a song's data is composed. Instrument Table ================ The instrument table is a series of 8-byte datas which is used globally for all songs and sound effects. The information it holds is volume envelope info, volume and pitch vibration depth/speed, and a random noise flag when used with the NES noise channel. There can be any number of instruments (up to 255). It seems those used for music are usually found first, and those used for sound effects next.. The location of the Instrument Table is found after the Song/SFX Address Table, before the first BGM's data. The instrument table has a pointer pointing to it, so that the sound engine knows where the Instrument Table is located. This is right before the Song/SFX Address Table, at Sound Engine Bank offset + $A41. Just like songs/sfx pointers, this is a Big-Endian memory pointer. For Megaman 3, the pointer is at $2CA51, and the table itself starts at $2CAC5. See the "Instruments" section at the end of the document for detailed info on the actual instrument data. Song Format =========== If the first byte in the sound data is $00, it's a song. Or else, it's actually a sound effect. The song is divided into 4 channels: Square 1, Square 2, Triangle (Bass, Bassdrums etc.) and Noise (Used as drums etc.) Following the first byte, comes four x 2-byte pointers, which points to the start of the data for each channel. These work exactly in the same manner as the pointers in the song adress table, so, to get the ROM address for one of the pointers: Just subtract $8000 and add the address of the Sound Engine Bank. The channel data is made up of commands and notes. Both use byte values to describe them. They can be mixed as you like. Commands use values 00 to 1F and notes 20 to FF. Commands tells how the notes shall sound, controls loops, tempo etc. Some of them have one or more operands (up to three), some have none. Below is a list of commands. In this list, each +[*something*] means there is an extra byte following the command that describes an operand. ----------------------------------------------------------------------------------------------------- Val MM2 Name Operands Comment ----------------------------------------------------------------------------------------------------- 00 Triplet Connect notes to make triplets. (Use before and after notes) 01 (2#) Connect Connect note length of one or more notes. (Use before first and last note) 02 (06) Dotted Note The next note becomes 1 and a half its original length. 03 OctPlus Swap Octave by 2 upwards, on and off. 04 Set Flags +[Value] Set some flags. See "Command $04 Flags." 05 (00) Speed +[High],+[Low] Higher Value means higher speed. Default: 01,00 06 Length +[Time] Set Note hold lenght (Time of Key off). $00 to $FF. 07 (03) Volume +[Volume] Set Volume ($00 - $0F) 08 Instrument +[Instrument] Set Instrument to use (01 and up). If 00, instrument table isn't used. 09 (05) Octave +[Octave] Set Octave (00-07, 08 and 09 gives lower octave than 00. 0A same as 00.) 0A Global Transpose +[Value] Transpose All Channels. Default: 00. 01 to 7F is higher. FF to 80 is lower. 0B (05) Transpose +[Value] Transpose current Channel. Default: 00. 01 to 7F is higher. FF to 80 is lower. 0C Tune +[Value] Tune Pitch. Default: 00. 01 to 7F is higher. FF to 80 is lower. 0D Slide +[Speed] Pitch slide between notes. 00=Disable. 01-FF = Enable. The higher the value, the faster the slide. 0E (04) Loop1 +[Times]+[High]+[Low] Loop, Counter 1. Times = Logical # of Times 0F (04) Loop2 +[Times]+[High]+[Low] Loop, Counter 2. Times = Logical # of Times 10 (04) Loop3 +[Times]+[High]+[Low] Loop, Counter 3. Times = Logical # of Times 11 (04) Loop4 +[Times]+[High]+[Low] Loop, Counter 4. Times = Logical # of Times 12 Break1 +[Flags]+[High]+[Low] Jump to Address if Loop1 is on last cycle, and set flags to [Flags] 13 Break2 +[Flags]+[High]+[Low] Jump to Address if Loop2 is on last cycle, and set flags to [Flags] 14 Break3 +[Flags]+[High]+[Low] Jump to Address if Loop3 is on last cycle, and set flags to [Flags] 15 Break4 +[Flags]+[High]+[Low] Jump to Address if Loop4 is on last cycle, and set flags to [Flags] 16 (04) Jump +[High]+[Low] Jump to Adresss 17 (09) End Channel End (not needed if the song loops infinitely.) 18 (02) Tone Type +[Type] Bits 0-1: Duty Cycle, bits 2-7: Not used. SNES SPC700 command notes (probably inaccurate): 07 Volume +[Volume] Set Volume. Max value is 135 ($87 hex). 18 Panning +[Value] 19 Global Volume? +[Volume] Max value is 135 ($87 hex). 1A Extended Command +[Command],+[Value] Seems to be used to control settings related to Pitch/Volume vibrato. Values of 'Command' seem to be: 00 = Set pitch vibrato depth 01 = Set volume tremolo depth 02 = Set Set vibrato/tremolo speed 1B Unknown Doesn't have operand. 1C Enable Reverb +[Setting] 01 = Enable, 00 = Disable. 1D Unknown +[Operand]?? 1E Unknown +[Operand]?? 1F Unknown +[Operand]?? MM1/2 conversion ---------------- The MM2 collumn is the commands in the Megaman 1 and 2 sound engines which has similar or almost similar operation as the command in this one. Note from Infidelity: "01 Connect section, In MM2, I found 21's and 22's before a set of notes. 21 means 2 notes held together to make it sound like 1 note, 22 means 3 notes held together to make it sound like 1 note." MM2 commands 07 and 08 controls volume slide and vibrato settings, so in a way they both relate to the effects of the 08 (instrument) command in this one. Note byte values: -------------------------------- Value Note Lenght -------------------------------- 20 Break 64th 21 C-0 64th 22 C#0 64th 23 D-0 64th 24 D#0 64th 25 E-0 64th 26 F-0 64th 27 F#0 64th 28 G-0 64th 29 G#0 64th 2A A-0 64th 2B A#0 64th 2C B-0 64th 2D C-1 64th 2E C#1 64th 2F D-1 64th 30 D#1 64th 31 E-1 64th 32 F-1 64th 33 F#1 64th 34 G-1 64th 35 G#1 64th 36 A-1 64th 37 A#1 64th 38 B-1 64th 39 C-2 64th 3A C#2 64th 3B D-2 64th 3C D#2 64th 3D E-2 64th 3E F-2 64th 3F F#2 64th -------------------------------- The following values have basically the same meaning as the values in the table above, except with different lenght: ("Whole note" is the longest.) 40-5F = 32th Note 60-7F = 16th Note 80-9F = 8th Note A0-BF = Quarter Note C0-DF = Half Note E0-FF = Whole Note The values follow the same order as the table above, for example, 40 gives a "32th Note" break, and 41 gives a "32th note" C-0. "Break" means no new note is played. It can be used for delay. The volume envelope will still fade out to silence for the duration of the break, if its not finished when the previous note ends. In "C-0", means C is the note and 0 is the relative octave. This means the number is relative to the current octave set with the 09 command. For example, if the octave is set to 02 with the 09 command, and you then place 3B (D-2), the actual octave will be 04 (02 + 02.) It might be a good idea to start with values 80-9F or A0-BF when writing a song from scratch, and then use shorter or longer notes as needed. Note byte values (Noise channel) -------------------------------- 21 equals to the lowest noise frequency, 30 to the highest. The values repeat from 31 towards 3F, all frequencies are repeated except the highest. Like with the tonal channels, the values from 40 to FF repeats the frequency setup, but with different note lengths. The frequency order is opposite from the values of the NES register, where the lowest value is the highest frequency. Detailed Information on Commands ================================ 00: Triplet ----------- This connects series of 3 notes together to make a single unit. Place it before the first note and after the last note to be affected. The number of notes connected must be dividable by 3, it seems. If not, the channel will eventually go out of sync with the other channels. Usage: 0,$81,$83,$85,0 0,$81,$83,$85,$87,$89,$8B,0 01: Connect ----------- This will combine the note length of two or more notes. Plce the command before the first note to connect, and again before the last note to connect, in order to disable it. Example: 1,$85,1,$45 ;8th note + 32nd note E-1 Its possible to change instrument settings and the like between the connected notes. This method can be used to start a vibrato effect in the middle of two notes, but technically it is two notes connected to become one. Example: $08,$04 ;Set instrument to $04. Instrument has no vibrato. $01 ;Begin connect. $85 ;1/2 of the note $08,$05 ;Set instrument to $05. Instrument has vibrato. $01 ;End connect $85 ;2/2 of the note 02: PlusHalf ------------ Adds one half length of the note length to the note following this command, making it half a time longer. Note: It seems this doesn't work for Whole Note ($E0-$FF). Usage: 2,$85,2,$85 06: Length ---------- This sets how long the note is held, or in other words what point in the note Key Off happens. (It is different from how long the note byte lasts, so it doesn't affect the synchronicity of the notes.) This affects the volume envelope, it decides at what relative point in the note's duration that the Release part of the envelope starts. At that point, Volume is faded down. The rate which volume fades depends on what Instrument is used, in some cases the sound changes to silence immediatedly. For the operand value, 00 is as early as possible in the note, FF is as late as possible (just before the start of whatever note comes next.) 80 will make the point be in the middle of the note. 08: Instrument -------------- Chooses if to use an instrument setting, and if so, which instrument to use from the instrument table. Instruments determine various volume and pitch effects. (See "Instruments" further down.) Value 00 means no instrument. The sound of notes will be pretty basic, with no envelope. In this case, for each note, when the key is released (timing depends on command 06), the volume will drop straight to 0. 01 or more makes the channel use a instrument. 01 means it will use the first eight bytes in the instrument table, 02 the next eight bytes, etc. 12/13/14/15 Break Function: --------------------------- This will cause the song to jump somewhere if the song is in a loop and its in the last cycle of it. (in NES memory, if the loop counter is 01.) The logic: If (Loop Counter - 1) = 0: Set Loop Counter to 0. Jump. 17: End ------- This command isn't really necessary for looped channels. Command $04 and Break Command Flags =================================== These are bits that are also changed through other commands and by other events. Command $04 and the Break commands ($12-$15) can be used to explicitly set any of these bits on. (Forcing them off can only be done for some of them, however.) MSB bit0: Connect mode flag 2. Becomes copy of bit1 when a new note has been initialized. bit1: Connect mode flag 1. Bit gets toggled on/off with Command 01. Cmd 04 always clears this bit, unless it's used to set it. bit2: Triplet mode flag. Bit gets toggled on/off with Command 00. Cmd 04 always clears this bit, unless it's used to set it. bit3: Dotted Note flag. Command 02 sets this bit. (Logic OR). It's cleared after the next note if set. bit4: Octave jump flag. Bit gets toggled on/off with command 03. Cmd 04 always clears this bit, unless it's used to set it. bit5-7: Octave set with Command 09. (Because it does an OR operation with the Flags memory byte, Cmd 09 can also be used to force any other of these bits on!) LSB When Octave is calculated, the lower 4 bits are used together as the index into a table. (It's at memory address $8923.) bit3 still always makes it only 2 Octaves higher, even if it's the highest bit of the four. Sound Effects ============= Sound Effect Data: BYTE Sound Effect Priority and Endless Loop bit. MSB bit0: Endless Loop bit bit1-7: Priority value LSB Priority value: Must be >0. Usually some value below $20. If a sound effect is initialized while another sound effect is playing, this byte decides which should be given priority. In other words, in such a case it will only play the new sound effect if this byte is greater than the Priority value of the sound effect that is already playing. Endless Loop bit: If this is set, the sound effect will loop forever. Also, there are other quirks with this. While the looped effect keeps playing, other sound effects can be played back, what happens depends on the new sound effect's priority value: If it's priority value is Less than the looped sfx, it will be disregarded. If it's priority value is Higher than the looped sfx, it will be played, and when it is finished, the looped sound effect will resume playing endlessly. If it's priority value is Equal to the looped sfx, it will init and the looped sfx will *not* play after this, it will stop. Also, the pitch of a looped sound effect can be tuned through a memory value, with a higher pitch, but not lower. This is apparently meant to be done by using Sound Id $F7, and calling $8003 with that in the A register and the pitch value in the Y register. It can be changed directly by memory address $D8. That value is only regarded when a looped sound effect is playing. The only instances I've seen of this bit used is with a couple sound effects in "Adventures in the Magic Kingdom" (Id's #2C and #31). Sound effects are divided into one or more segments. Each segment has a given length in VBlank frames. For each segment, there is a byte deciding which channels to use, and then follows data for each used channel. The sound effects continues until the first byte of a segment has the upper bit set. A segment can be looped, so that it repeats a set number of times. Segment data: { BYTE Command Enable Bits A MSB bit0: Bit Flag : End of Sound Effect? (1 = Yes, 0 = No) bit5: Bit Flag : Set Transpose (for all channels) bit6: Bit Flag : Note Hold Length (for all channels) bit7: Bit Flag : Loop Bit LSB If the highest bit is set, it means the end of the sound effect's data. (Usually, in games' data, all bits are set, so the value is $FF, not $80.) Depending on what bits are set, more bytes follow, setting up variables pertaining to all used channels in this segment, or in some cases a loop. If Bit Flag : Loop Bit is Set ( = 1) { BYTE Loop Times BYTE Pointer, High Byte BYTE Pointer, Low Byte } The loop bit is to be used on a new segment after the segment to actually repeat. When the loop information is read, if the loop is not completed it immediatedly jumps to the pointer. At the pointer must be the beginning of a segment. The pointer is like other pointers in the sound data, a 16-bit Big-Endian memory pointer. ASM Example: $09 ;start of sfx data label1: $02,$FF,$04,$02,$0F,$FF,$FF,$FF,$FF,$55 $01 ;start of new segment, $01 indicates loop. $08 ;loop 8 times high(label1),low(label1) ;pointer to "label1", which is at the start of a segment. $00,$00,$FF ;rest of segment. 0 frame length, no NES channels have data, the FF ends the sound effect. If Bit Flag : Note Hold Length is Set ( = 1) { BYTE Note Hold Length This works exactly the same way as command 06 with BGM's. The value affects all used channels in this segment EXCEPT Triangle channel, it's set in a different way. } If Bit Flag : Set Transpose is Set ( = 1) { BYTE Transpose. } BYTE Duration to play all channels in this segment, in Vblank frames. BYTE NES Channels to use (Any combination can be used.) MSB bit4: Noise bit5: Triangle bit6: Square 2 bit7: Square 1 LSB At this point, channel data is present for each used channel. The order is Square 1, Square 2, Triangle, then Noise. For each used channel { Each channel has settings that can be changed for each segment. First there is a byte containing bits telling which settings are to be set. For each bit that is set, there will be a byte for that setting coming. (Similarly to "Command Enable Bits A".) The setting will stay in memory from one segment to the next, so you don't have to set up the same value twice in a row. Channel data: BYTE Command Enable Bits B MSB bit3 : Bit Flag : Pitch Tune Byte bit4 : Bit Flag : Pitch Slide Byte bit5 : Bit Flag : Volume/Triangle Note Hold Length Byte bit6 : Bit Flag : Duty Cycle Byte bit7 : Bit Flag : Instrument Byte LSB If Bit Flag : Instrument Byte is Set ( = 1) {BYTE Instrument } If Bit Flag : Duty Cycle Byte is Set ( = 1) {BYTE Duty Cycle } If Bit Flag : Volume/Triangle Note Hold Length Byte is Set ( = 1) {BYTE Value } When used for Square and Noise channels, this is 4-bit channel volume. When used for Triangle channel, this is Note Hold Length. It must be present to set that for Triangle. If Bit Flag : Pitch Slide Byte is Set ( = 1) {BYTE Pitch Slide Byte } Values 01-7F: Slide Down Values 80-FF: Slide Up If Bit Flag : Pitch Tune Byte is Set ( = 1) {BYTE Pitch Tune } Values 01-7F: Lower pitch. Greater value means lower pitch. Values 80-FF: Higher pitch. Lower value means higher pitch. BYTE Semitone / Noise Frequency Unlike BGM, the values span all octaves. The higher the value, the higher the pitch. For Noise channel, the value range is 00 to 0F. This byte is always present for each used chnnel. } End of channel's data. } End of segment data. After finishing playing back the segment, it starts to read a new segment. Instrument, Duty Cycle and Volume Byte functions the same way as for music. Instruments =========== Each instrument uses 8 bytes. The information associated with each instrument is volume envelope, pitch vibrato and volume tremolo. Additionally, for the noise channel it decides if the channel is to produce sound with the Random Noise bit set. (Metallic-like sound) Byte Layout: Byte# Function 1 Attack parameter (00-1F) 2 Decay parameter (00-1F) 3 Sustain level (8-bit, 00-FF) 4 Release parameter (00-1F) 5 Vibrato/Tremolo Speed and Reset bit MSB 0: Reset bit. If this is Set, then the Vibrato and Tremolo phase counters will reset at each new note. 1-7: Speed used for both Vibrato and Tremolo. LSB 6 Pitch Vibrato Depth 7 Volume Tremolo Depth 8 Noise Channel - Random bit (Highest bit. Lower 7 bits are unused.) Envelope: The volume envelope is purely an ADSR (Attack, Decay, Sustain, Release). There is an article on Wikipedia containing info on ADSR here: http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope The Attack, Decay and Release parameters each have a value from 00 to 1F. (They are look-up values into a table, more later on). The value decides the rate that the level is increased or decreased for each part of the envelope. 01 is slowest and 1F is fastest. A value of 00 makes the envelope not change level, except for Decay. If the Decay value is 00, it will immediatedly set the envelope level to Sustain (once Attack has finished rising to peak level) The engine keeps a 8-bit value of the current envelope level. When calculating the actual volume value to output to the NES registers, this value is used to subtract relatively from that. That is, the upper 4 bits of the envelope level. The relation to what is subtracted from the volume is like this: Current envelope level: Subtracted from output volume: F0-FF 0 E0-EF -1 D0-DF -2 C0-CF -3 ..... ... 00-0F -15 (Results in silence no matter what.) For example, if the volume value set with command 07 is #$0B, and the envelope is currently at Sustain level, and the instrument's Sustain value is 80, the resulting NES volume will be #4. In the games, Sustain level is usually a value divisible by 16 (so F0, E0, D0, C0 and so on.). It can be anything, but because the NES volumes are only 4-bit, it makes no difference if the sustain value is E0 or E8. It gives the same result. Once the Sustain level has been reached, that is used until Key off. This happens some time within the duration of the note, this depends on what is set with command 06. A lower value set with 06 means Key off happens closer to when the note starts, a higher value means closer to when it ends. As far as I know, if $FF is set with command 06 it makes Release either never happen or very briefly (1 frame). If the value is low enough it will skip Attack and Decay if those aren't finished, and continue with Release from whatever level the envelope is at that point. Once the current note is done, if a Break Id follows ($E0, $C0, $A0, etc.), then the envelope level will keep decreasing until 0 in Release state. (It will go Release regardless if it was Attack, Decay or Sustain before). Attack, Decay and Release parameters function as indexes into a table, to get the value to actually add or subtract to/from the current envelope level each frame. The table's contents are as follows: (It's memory address is usually $88F6) 00 to 07: 00, 01, 02, 03, 04, 05, 06, 07 08 to 0F: 08, 09, 0A, 0B, 0C, 0E, 0F, 10 10 to 17: 12, 13, 14, 16, 18, 1B, 1E, 23 18 to 1F: 28, 30, 3C, 50, 7E, 7F, FE, FF The ADSR envelope is handled differently for the Triangle channel, which practically only has two volume states, on and off. Links ===== Disassembly based on Mega Man 4: http://www.romhacking.net/documents/634/